package com.wuzhipeng.heart.user.service.impl;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wuzhipeng.heart.user.config.UserContext;
import com.wuzhipeng.heart.user.convention.AppointmentsStatusConstants.AppointmentsStatus;
import com.wuzhipeng.heart.user.convention.exception.ClientException;
import com.wuzhipeng.heart.user.dao.entity.Appointments;
import com.wuzhipeng.heart.user.dao.entity.Status;
import com.wuzhipeng.heart.user.dao.entity.Therapist;
import com.wuzhipeng.heart.user.dao.entity.Users;
import com.wuzhipeng.heart.user.dao.mapper.AppointmentsMapper;
import com.wuzhipeng.heart.user.dto.request.*;
import com.wuzhipeng.heart.user.service.IAppointmentsService;
import com.wuzhipeng.heart.user.service.IStatusService;
import com.wuzhipeng.heart.user.service.ITherapistService;
import com.wuzhipeng.heart.user.service.IUsersService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wuzhipeng
 * @since 2024-12-25
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AppointmentsServiceImpl extends ServiceImpl<AppointmentsMapper, Appointments> implements IAppointmentsService {

    private final IUsersService usersService;
    private final ITherapistService therapistService;
    private final AppointmentsMapper appointmentsMapper;
    private final IStatusService statusService;
    @Override
    public List<String> getAvailableTime(TherapistAvailableTimeDTO therapistAvailableTimeDTO) {


        List<Appointments> appointmentsList = appointmentsMapper.selectByDate(therapistAvailableTimeDTO);
        statusService.updateConsultCount(therapistAvailableTimeDTO.getTherapistPhone());
        List<String> list = new ArrayList<>();
        for (Appointments appointments : appointmentsList) {
            list.add(appointments.getConsultationTime());
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addAppointment(MakeAppointmentsDTO makeAppointmentsDTO) {
        Users users = usersService.getUserByPhone(UserContext.getPhone());
        LambdaUpdateWrapper<Appointments> wrapper = Wrappers.lambdaUpdate(Appointments.class)
                .eq(Appointments::getConsultationTime, makeAppointmentsDTO.getAppointmentTime())
                .eq(Appointments::getConsultantPhone,makeAppointmentsDTO.getTherapistPhone())
                .eq(Appointments::getConsultationDate, makeAppointmentsDTO.getAppointmentDate())
                .eq(Appointments::getConsultationStatus, AppointmentsStatus.WAITING)
                .set(Appointments::getConsultationStatus, AppointmentsStatus.APPOINTED)
                .set(Appointments::getClientPhone,users.getPhone())
                .set(Appointments::getClientName,users.getUsername());
        int update = appointmentsMapper.update(wrapper);
        log.info("更新预约信息，更新条数：{}", update);
    }

    @Override
    public List<UserAppointmentsDTO> getUserAppointments() {
        LambdaQueryWrapper<Appointments> wrapper = Wrappers.lambdaQuery(Appointments.class)
                .eq(Appointments::getClientPhone, UserContext.getPhone())
               .orderByDesc(Appointments::getConsultationDate);
        List<Appointments> appointmentsList = appointmentsMapper.selectList(wrapper);
        List<UserAppointmentsDTO> userAppointmentsDTOList = new ArrayList<>();
        for (Appointments appointments : appointmentsList) {
            String status=switch (appointments.getConsultationStatus())
            {
                case AppointmentsStatus.APPOINTED:
                    yield "pending";
                case AppointmentsStatus.WAITING:
                    yield "未预约";
                case AppointmentsStatus.CANCELLED:
                    yield "cancelled";
                case AppointmentsStatus.FINISHED:
                    yield "completed";
                default:
                    throw new ClientException("预约状态异常");
            };
            String statusText=switch (appointments.getConsultationStatus())
                    {
                case AppointmentsStatus.APPOINTED:
                    yield "预约中";
                case AppointmentsStatus.WAITING:
                    yield "未预约";
                case AppointmentsStatus.CANCELLED:
                    yield "已取消";
                case AppointmentsStatus.FINISHED:
                    yield "已完成";
                default:
                    throw new ClientException("预约状态异常");
            };
            UserAppointmentsDTO userAppointmentsDTO = UserAppointmentsDTO.builder()
                    .id(Long.valueOf(appointments.getAppointmentID()))
                    .therapistName(appointments.getConsultantName())
                    .date(appointments.getConsultationDate().toString())
                    .time(appointments.getConsultationTime())
                    .status(status)
                    .type("面对面咨询")
                    .location("华北电力大学")
                    .statusText(statusText)
                    .build();
            userAppointmentsDTOList.add(userAppointmentsDTO);
        }
        return userAppointmentsDTOList;
    }

    @Override
    public void cancelAppointment(Long id) {
        LambdaUpdateWrapper<Appointments> wrapper = Wrappers.lambdaUpdate(Appointments.class)
                .eq(Appointments::getAppointmentID, id)
                .set(Appointments::getConsultationStatus, AppointmentsStatus.CANCELLED);
        int update = appointmentsMapper.update(wrapper);
        log.info("取消预约，更新条数：{}", update);
        LambdaQueryWrapper<Appointments> queryWrapper = Wrappers.lambdaQuery(Appointments.class)
                .eq(Appointments::getAppointmentID, id);
        Appointments appointments = appointmentsMapper.selectOne(queryWrapper);
        appointments.setClientName("");
        appointments.setClientPhone("");
        appointments.setConsultationStatus(AppointmentsStatus.WAITING);
        appointments.setAppointmentID(null);
        int insert = baseMapper.insert(appointments);
        log.info("更新预约信息，插入条数：{}", insert);

    }

    /**
     * 获取用户的预约统计信息
     * @return
     */
    @Override
    public StatsDTO getTherapistStats() {
        LambdaQueryWrapper<Appointments> wrapper = Wrappers.lambdaQuery(Appointments.class)
                .eq(Appointments::getConsultantPhone, UserContext.getPhone())
                .eq(Appointments::getConsultationDate, LocalDate.now());
        Long count = appointmentsMapper.selectCount(wrapper);
        List<Appointments> appointments= appointmentsMapper.selectWeekCount(UserContext.getPhone());
        int weekCount=appointments.size();
        LambdaQueryWrapper<Status> userWrapper = Wrappers.lambdaQuery(Status.class)
                .eq(Status::getPhone, UserContext.getPhone());
        Status status = statusService.getOne(userWrapper);

        int ClientCount=status==null?0:status.getQueryCount();
        StatsDTO statsDTO = StatsDTO.builder()
                .todayAppointments(count.intValue())
                .totalClients(ClientCount)
                .weeklyConsultations(weekCount)
                .satisfaction(RandomUtil.randomInt(90,95))
                .build();
        return statsDTO;
    }

    @Override
    public List<TodayAppointmentsDTO> getTherapistScheduleToday() {
        List<Appointments> appointments= appointmentsMapper.selectTodayAppointments(UserContext.getPhone());
        List<TodayAppointmentsDTO> todayAppointmentsDTOList=new ArrayList<>();
        for (Appointments appointments1 : appointments) {
            String status=switch (appointments1.getConsultationStatus())
            {
                case AppointmentsStatus.APPOINTED:
                    yield "pending";
                case AppointmentsStatus.WAITING:
                    yield "未预约";
                case AppointmentsStatus.CANCELLED:
                    yield "cancelled";
                case AppointmentsStatus.FINISHED:
                    yield "completed";
                default:
                    throw new ClientException("预约状态异常");
            };
            String statusText=switch (appointments1.getConsultationStatus())
                    {
                case AppointmentsStatus.APPOINTED:
                    yield "预约中";
                case AppointmentsStatus.WAITING:
                    yield "未预约";
                    case AppointmentsStatus.CANCELLED:
                    yield "已取消";
                case AppointmentsStatus.FINISHED:
                    yield "已完成";
                default:
                    throw new ClientException("预约状态异常");
            };
            TodayAppointmentsDTO todayAppointmentsDTO = TodayAppointmentsDTO.builder()
                    .id(String.valueOf(appointments1.getAppointmentID()))
                    .date(appointments1.getConsultationDate().toString())
                    .time(appointments1.getConsultationTime())
                    .clientName(appointments1.getClientName())
                    .type("面对面咨询")
                    .status(status)
                    .statusText(statusText)
                    .build();
            todayAppointmentsDTOList.add(todayAppointmentsDTO);
        }
        return todayAppointmentsDTOList;
    }

    @Override
    public List<ScheduleDTO> getTherapistSchedule(String startDate) {
        List<Appointments> appointments= appointmentsMapper.selectSchedule(UserContext.getPhone(), DateUtil.parseDate(startDate));
        List<ScheduleDTO> scheduleDTOList=new ArrayList<>();
        for (Appointments appointments1 : appointments) {
            String status=switch (appointments1.getConsultationStatus())
            {
                case AppointmentsStatus.APPOINTED->"booked";
                case AppointmentsStatus.WAITING->"selected";
                case AppointmentsStatus.CANCELLED->"cancelled";
                case AppointmentsStatus.FINISHED->"completed";
                default->throw new ClientException("预约状态异常");
            };
            String statusText=switch (appointments1.getConsultationStatus())
                    {
                case AppointmentsStatus.APPOINTED->"预约中";
                case AppointmentsStatus.WAITING->"可被约";
                case AppointmentsStatus.CANCELLED->"已取消";
                case AppointmentsStatus.FINISHED->"已完成";
                default-> throw new ClientException("预约状态异常");
            };
            ScheduleDTO scheduleDTO = ScheduleDTO.builder()
                    .date(appointments1.getConsultationDate().toString())
                    .timeSlot(appointments1.getConsultationTime())
                    .type("offline")
                    .status(status)
                    .statusText(statusText)
                    .build();
            scheduleDTOList.add(scheduleDTO);
        }
        return scheduleDTOList;
    }

    @Override
    public void addTherapistSchedule(ScheduleDTO scheduleDTO) {

        String time = scheduleDTO.getTimeSlot().split("-")[1];
        SimpleDateFormat df = new SimpleDateFormat("HH:mm");
        try {
            Date nowTime = df.parse(df.format(new Date()));
            boolean after = nowTime.after(df.parse(time));
            if (after) {
                throw new ClientException("预约时间必须在9:00之后");
            }
        }
        catch (Exception e) {
            throw new ClientException("预约时间必须在9:00之后");
        }

        Therapist therapistByPhone = therapistService.getTherapistByPhone(UserContext.getPhone());
        Appointments appointments=Appointments.builder()
                .ConsultantPhone(UserContext.getPhone())
                .ConsultantName(therapistByPhone.getName())
                .ConsultationDate(LocalDate.parse(scheduleDTO.getDate()))
                .ConsultationTime(scheduleDTO.getTimeSlot())
                .ConsultationStatus(AppointmentsStatus.WAITING)
                .build();
        int insert = baseMapper.insert(appointments);
        log.info("添加预约信息，插入条数：{}", insert);

    }

    @Override
    public List<AppointmentRecordsDTO> getTherapistRecords() {
        LambdaQueryWrapper<Appointments> wrapper = Wrappers.lambdaQuery(Appointments.class)
                .eq(Appointments::getConsultantPhone, UserContext.getPhone())
                .orderByDesc(Appointments::getConsultationDate);
        List<Appointments> appointments=baseMapper.selectList(wrapper);
        List<AppointmentRecordsDTO> appointmentRecordsDTOList=new ArrayList<>();
        for (Appointments appointments1 : appointments) {
            String status=switch (appointments1.getConsultationStatus())
            {
                case AppointmentsStatus.APPOINTED:
                    yield "pending";
                case AppointmentsStatus.WAITING:
                    yield "未预约";
                case AppointmentsStatus.CANCELLED:
                    yield "cancelled";
                case AppointmentsStatus.FINISHED:
                    yield "completed";
                default:
                    throw new ClientException("预约状态异常");
            };
            ClientInfoDTO clientInfoDTO = ClientInfoDTO.builder()
                    .name(appointments1.getClientName())
                    .phone(appointments1.getClientPhone())
                    .build();
            AppointmentRecordsDTO appointmentRecordsDTO = AppointmentRecordsDTO.builder()
                    .id(appointments1.getAppointmentID())
                    .date(appointments1.getConsultationDate().toString())
                    .timeSlot(appointments1.getConsultationTime())
                    .clientInfo(clientInfoDTO)
                    .status(status)
                    .build();
            appointmentRecordsDTOList.add(appointmentRecordsDTO);
        }
        return appointmentRecordsDTOList;
    }

    @Override
    public void deleteExpiredAppointments(List<Integer> ids) {
        baseMapper.deleteBatchIds(ids);
    }

    @Override
    public List<Appointments> getAllAppointmentsByDate() {
        LambdaQueryWrapper<Appointments> wrapper = Wrappers.lambdaQuery(Appointments.class)
                .le(Appointments::getConsultationDate, LocalDate.now());
        return baseMapper.selectList(wrapper);
    }
}
